/*
 * FuzzyUtils.cpp
 *
 *  Created on: 07-01-2011
 *      Author: Piotr
 */

#include "AI/fuzzy/FuzzyUtils.hpp"
#include "utils/MathUtils.hpp"
#include "utils/RangedValue.hpp"

const float FuzzyUtils::MEMBER = 1.0f;
const float FuzzyUtils::NOT_MEMBER = 0.0f;

float FuzzyUtils::calculateLinearFuncion(float x, float xNotMember, float xMember)
{
	return calculateLinearFuncion(x, Vector(xNotMember, NOT_MEMBER), Vector(xMember, MEMBER));
}

float FuzzyUtils::calculateLinearFuncion(float x, const Vector& p0, const Vector& p1)
{
	if(MathUtils::isEqual(p1.getX(), p0.getX()))
	{
		if(MathUtils::isEqual(p1.getX(), x))
		{
			return MEMBER;
		}
		return NOT_MEMBER;
	}

	float a = (p1.getY() - p0.getY()) / (p1.getX() - p0.getX());
	float b = p0.getY() - p0.getX() * a;
	return a * x + b;
}

float FuzzyUtils::getMembershipValue(float value, float xMin, float xMax)
{
	if(value <= xMin || value >= xMax || xMin > xMax)
	{
		return NOT_MEMBER;
	}

	float peek = (xMax + xMin) / 2;
	if(value <= peek)
	{
		return calculateLinearFuncion(value, xMin, peek);
	}
	return calculateLinearFuncion(value, xMax, peek);
}

float FuzzyUtils::getMembershipValue(float value, float xMin, float xPeek1, float xPeek2,
		float xMax)
{
	if(value <= xMin || value >= xMax || xPeek1 < xMin || xPeek1 >= xMax || xPeek2 <= xMin || xPeek2
			> xMax || xPeek1 > xPeek2)
	{
		return NOT_MEMBER;
	}

	if(value >= xPeek1 && value <= xPeek2)
	{
		return MEMBER;
	}

	if(value < xPeek1)
	{
		return calculateLinearFuncion(value, xMin, xPeek1);
	}
	return calculateLinearFuncion(value, xMax, xPeek2);
}

float FuzzyUtils::getMembershipValueRightInf(float value, float xMin, float xPeek)
{
	if(value <= xMin)
	{
		return NOT_MEMBER;
	}

	if(value >= xPeek)
	{
		return MEMBER;
	}

	return calculateLinearFuncion(value, xPeek, xMin);
}

float FuzzyUtils::getMembershipValueLeftInf(float value, float xPeek, float xMax)
{
	if(value >= xMax)
	{
		return NOT_MEMBER;
	}

	if(value <= xPeek)
	{
		return MEMBER;
	}

	return calculateLinearFuncion(value, xMax, xPeek);
}

float FuzzyUtils::fuzzyAnd(float value1, float value2)
{
	return value1 > value2? value2 : value1;
}

float FuzzyUtils::fuzzyOr(float value1, float value2)
{
	return value1 > value2? value1 : value2;
}

float FuzzyUtils::fuzzyNot(float value)
{
	return 1.0f - value;
}

